// postgres_io_binary.cpp : binary input and output from postgreSQL database
//

#if _MSC_VER > 1000
#pragma warning( disable :  4511 4512)
// nasty hack for VC++ non-compliance with standard C++ for loop declaration scope
#define for if (0); else for
#endif
#include <fstream>
#include <iostream>
#include <assert.h>
#include "postgres_io_binary.h"
#include <boost/smart_ptr.hpp>

using std::ofstream;
using std::ifstream;
using std::string;
using std::ostream;


/*
	PostgreSQL binary tuple format:
		int16 fieldcnt eg.3
		fixedlen field int16 len==bytes of following data, non-padded data
		varialen field int16 ==-1 int32 len of padded data + 4(self), non padded data
		null field     int16 == 0
		end with -1
*/










//***************************************************************************************

//		Functions for io to binary streams in PostgreSQL format

//***************************************************************************************
//_______________________________________________________________________________________

//	pg_read_str

//		utility function for reading binary to a stream

//_______________________________________________________________________________________
const char* pg_read_str(ifstream& istrm)
{
	static int buf_len = 0;
	static boost::scoped_array<char> buf;

	// variable type field always has a size of -1
	short sz = read_binary<short>(istrm);
	assert(sz == -1);

	// length includes size of word holding the length value!
	int len = read_binary<int>(istrm) - 4;

	// get memory if necessary
	if (len + 1 > buf_len)
	{
		// round to nearest multiple of 2
		buf_len = (((len + 2) >> 2) << 2);
		if (buf_len < 32)
			buf_len = 32;
		assert (buf_len >= len+1);
		buf.reset(new char[buf_len]);
	}

	istrm.read(buf.get(), len);
	(buf.get())[len] = 0;

	return buf.get();
}


//_______________________________________________________________________________________

//		utility functions for writing binary to a stream

//_______________________________________________________________________________________
void pg_write_str(ostream& os, const string& str)
{
	short sz = -1;
	os.write((char*)&sz, sizeof(short));
	int len = str.length() + 4;
	os.write((char*)&len, sizeof(len));
	os.write(str.c_str(), str.length());
}
